package logic;

import dto.MedicoDTO;
import dto.PacienteDTO;
import dto.TurnoDTO;
import java.sql.SQLException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import jr.LiquidacionJR;
import util.InputHelper;

/**
 *
 * @author lucifer
 */
public class LiquidacionParticular {

  // La liquidacion de particulares se ordena por día y por médico.
  // Si la semana está incompleta, el reporte muesta las liquidaciones hasta el
  // día actual.

  private LocalDate monday;
  private ArrayList<TurnoDTO> turnosDeLaSemana;

  private double[] totalPorDia; // [7]double -> 0:lunes, 1:martes, 2:miercoles,…
  private Map<Integer, Double> totalPorMedico;
  private Map<Integer, Double>[] totalDiarioPorMedico;
  private double total;

  // Jasper crap, sorry
  private String medicos;
  private String medicosTotales;

  public LiquidacionParticular(LocalDate monday) throws SQLException {
    if ((this.monday = monday).getDayOfWeek() != DayOfWeek.MONDAY) {
      throw new IllegalArgumentException("?day is not monday");
    }

    // Obra social zero means particular.
    turnosDeLaSemana = Turno.SearchTurnosAsistidosByObraSocialFromDateToDate(0, monday, monday.plusDays(6), false);
    totalPorDia = new double[7];
    totalPorMedico = new HashMap<>();
    totalDiarioPorMedico = new HashMap[7];
    for (int i = 0; i < 7; i++) {
      totalDiarioPorMedico[i] = new HashMap<>();
    }

    int dia;
    int idMedico;

    for (TurnoDTO t : turnosDeLaSemana) {
      if (totalPorMedico.containsKey(idMedico = t.getIdMedico())) {
        continue;
      }
      totalPorMedico.put(idMedico, 0.0);
    }

    for (TurnoDTO t : turnosDeLaSemana) {
      if (totalDiarioPorMedico[dia = t.getFecha().getDayOfWeek().getValue() - 1].containsKey(idMedico = t.getIdMedico())) {
        continue;
      }
      totalDiarioPorMedico[dia].put(idMedico, 0.0);
    }

    setTotales();
  }

  private void setTotales() throws SQLException {
    int dia;
    int idMedico;
    for (TurnoDTO t : turnosDeLaSemana) {
      totalPorDia[dia = t.getFecha().getDayOfWeek().getValue() - 1] += t.getMontoConsulta();
      idMedico = t.getIdMedico();
      totalPorMedico.replace(idMedico, totalPorMedico.get(idMedico) + t.getMontoConsulta());
      totalDiarioPorMedico[dia].replace(idMedico, totalDiarioPorMedico[dia].get(idMedico) + t.getMontoConsulta());
    }

    // Jasper crap, sorry
    MedicoDTO m;
    medicos = "";
    medicosTotales = "";
    for (Integer mid : totalPorMedico.keySet()) {
      m = Medico.SearchByID(mid);
      medicos += String.format("%s %s\n", m.getNombre(), m.getApellido());
      medicosTotales += String.format("$ %9.2f\n", totalPorMedico.get(mid));
    }

    for (int i = 0; i < 7; i++) {
      total += totalPorDia[i];
    }
  }

  public ArrayList<LiquidacionJR> GenerarLiquidacion() throws SQLException {
    ArrayList<LiquidacionJR> l = new ArrayList<>();

    if (turnosDeLaSemana.isEmpty()) {
      l.add(new LiquidacionJR(
        monday.format(DateTimeFormatter.ofPattern("'lunes' dd/MM/yyyy")),
        "", "", "", "",
        monday.format(DateTimeFormatter.ofPattern("'semana del lunes' dd/MM/yyyy")), "-",
        "no hubo consultas", "-", "", "", "",
        "", "", "", "", "$ 0", "$ 0"));
      return l;
    }

    int dia;
    for (TurnoDTO t : turnosDeLaSemana) {
      MedicoDTO m = Medico.SearchByID(t.getIdMedico());
      PacienteDTO p = Paciente.SearchByID(t.getIdPaciente());

      l.add(new LiquidacionJR(
        monday.format(DateTimeFormatter.ofPattern("'lunes' dd/MM/yyyy")),
        String.format("%s %s", m.getNombre(), m.getApellido()), Especialidad.SearchByID(m.getIdEspecialidad()).getNombre(), m.getMatricula(), String.format("$%9.2f", t.getMontoConsulta()),
        String.format("%s %s", InputHelper.DayConverter(t.getFecha().getDayOfWeek()), t.getFecha().toLocalDate().format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))), t.getFecha().toLocalTime().toString(),
        String.format("%s %s", p.getNombre(), p.getApellido()), String.format("%d", p.getDni()), null, null, null,
        medicos, medicosTotales,
        String.format("$%9.2f", totalPorMedico.get(m.getId())), String.format("$%10.2f", totalPorDia[dia = t.getFecha().getDayOfWeek().getValue() - 1]),
        String.format("$%9.2f", totalDiarioPorMedico[dia].get(m.getId())),
        String.format("$%10.2f", total)
      ));
    }

    return l;
  }

}
